package com.vm.osm.business.util;

import com.google.gson.Gson;
import com.vm.osm.business.dto.rsp.HttpRspResult;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.*;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;

/**
 * <p>HttpUtil</p>
 *
 */
public abstract class HttpUtil {
    private HttpUtil() {
        throw new RuntimeException("HttpUtil.class can't be instantiated");
    }

    private static final Logger LOG = Logger.getLogger(HttpUtil.class);

    /**
     * 支持HTTP_CLIENT的多线程使用
     */
    private static final MultiThreadedHttpConnectionManager
            HTTP_CONNECTION_MANAGER = new MultiThreadedHttpConnectionManager();
    private static final HttpClient HTTP_CLIENT = new HttpClient(HTTP_CONNECTION_MANAGER);

    /**
     * httpGetReq
     *
     * @param url 服务路径
     * @return
     * @throws IOException
     */
    public static HttpRspResult httpGetReq(String url){
        GetMethod method = null;
        HttpRspResult httpRspResult = new HttpRspResult();
        try{
            LOG.info("get url : " + url);
            method = new GetMethod(url);
            int httpStatus = HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);

            httpRspResult.setHttp_status(httpStatus);
            httpRspResult.setResponse_str(rspJson);
            return httpRspResult;
        }catch (IOException e){
            LOG.error("HttpGet失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }


    /**
     * httpGetReq
     *
     * @param url 服务路径
     * @return
     * @throws IOException
     */
    public static HttpRspResult httpGetReq(String url,Map<String,Object> params){
        GetMethod method = null;
        HttpRspResult httpRspResult = new HttpRspResult();
        try{
            String reqParam = buildQuery(params,"UTF-8");
            LOG.info("get url : " + url+"?"+reqParam);
            method = new GetMethod(url+"?"+reqParam);
            int httpStatus = HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);

            httpRspResult.setHttp_status(httpStatus);
            httpRspResult.setResponse_str(rspJson);
            return httpRspResult;
        }catch (IOException e){
            LOG.error("HttpGet失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }

    /**
     * httpGetReq
     *
     * @param url 服务路径
     * @return
     * @throws IOException
     */
    public static byte[] httpGetReqForBytes(String url,Map<String,Object> params){
        GetMethod method = null;
        try{
            String reqParam = buildQuery(params,"UTF-8");
            LOG.info("get url : " + url+"?"+reqParam);
            method = new GetMethod(url+"?"+reqParam);
            HTTP_CLIENT.executeMethod(method);
            return method.getResponseBody();
        }catch (IOException e){
            LOG.error("HttpGet失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }

    public static String postWithHeader(String url, Map<String, String> paramMap, Map<String, String> headers)
            throws Exception{

        PostMethod method = null;
        try{
            LOG.info("post url : " + url);
            method = new PostMethod(url);
            Gson gson = new Gson();
            String json = gson.toJson(paramMap);
            LOG.info("req post data : " + json);
            for(String key:paramMap.keySet()){
                method.addParameter(key, paramMap.get(key));
            }
            for(String key:headers.keySet()){
                method.addRequestHeader(key, headers.get(key));
            }
            HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);
            return rspJson;
        }catch (IOException e ){
            LOG.error("HttpPost失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }

    /**
     * httpDeleteReq
     *
     * @param url 服务路径
     * @return
     * @throws IOException
     */
    public static HttpRspResult httpDeleteReq(String url){
        DeleteMethod method = null;
        try{
            HttpRspResult httpRspResult = new HttpRspResult();
            LOG.info("delete url : " + url);
            method = new DeleteMethod(url);
            int httpStatus = HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);
            httpRspResult.setHttp_status(httpStatus);
            httpRspResult.setResponse_str(rspJson);
            return httpRspResult;
        }catch (IOException e){
            LOG.error("HttpDelete失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }

    /**
     * httpPutReq
     *
     * @param url    服务路径
     * @param params 请求参数
     * @return http应答内容
     * @throws IOException
     */
    public static String httpPutReq(String url, Object params) {
        PutMethod method = null;
        try{
            LOG.info("put url : " + url);
            method = new PutMethod(url);
            Gson gson = new Gson();
            String json = gson.toJson(params);
            LOG.info("req data : " + json);
            RequestEntity entity = new StringRequestEntity(json, "application/json", "UTF-8");
            method.setRequestEntity(entity);
            HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);
            return rspJson;
        }catch (IOException e ){
            LOG.error("HttpPut失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }

    /**
     * httpPostReq
     *
     * @param url    服务路径
     * @param params 请求参数
     * @return http应答内容
     * @throws IOException
     */
    public static String httpPostReq(String url, Object params) {
        PostMethod method = null;
        try{
            LOG.info("post url : " + url);
            method = new PostMethod(url);
            Gson gson = new Gson();
            String json = gson.toJson(params);
            LOG.info("req post data : " + json);
            RequestEntity entity = new StringRequestEntity(json, "application/json", "UTF-8");
            method.setRequestEntity(entity);
            HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);
            return rspJson;
        }catch (IOException e ){
            LOG.error("HttpPost失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }

    /**
     * httpPostReq
     *
     * @param uri    服务路径
     * @param params 请求参数
     * @return http应答内容
     * @throws IOException
     */
    public static HttpRspResult httpPostReq(String uri, Map<String, String> params) {
        PostMethod method = null;
        HttpRspResult httpRspResult = new HttpRspResult();
        try{
            method = new PostMethod(uri);
            Gson gson = new Gson();
            String json = gson.toJson(params);
            LOG.info("req data : " + json);
            RequestEntity entity = new StringRequestEntity(json, "application/json", "UTF-8");
            method.setRequestEntity(entity);
            Integer status = HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);
            httpRspResult.setHttp_status(status);
            httpRspResult.setResponse_str(rspJson);
            return httpRspResult;
        }catch (IOException e ){
            LOG.error("HttpPost失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }


    /**
     * httpPutReq
     *
     * @param uri    服务路径
     * @param params 请求参数
     * @return http应答内容
     * @throws IOException
     */
    public static HttpRspResult httpPutReq(String uri, Map<String, String> params) {
        PutMethod method = null;
        HttpRspResult httpRspResult = new HttpRspResult();
        try{
            method = new PutMethod(uri);
            Gson gson = new Gson();
            String json = gson.toJson(params);
            LOG.info("req data : " + json);
            RequestEntity entity = new StringRequestEntity(json, "application/json", "UTF-8");
            method.setRequestEntity(entity);
            Integer status = HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);
            httpRspResult.setHttp_status(status);
            httpRspResult.setResponse_str(rspJson);
            return httpRspResult;
        }catch (IOException e ){
            LOG.error("HttpPut失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }



    /**
     * httpPostReq
     *
     * @param url     服务路径
     * @param content 请求内容
     * @return http应答内容
     * @throws IOException
     */
    public static String httpPostReq(String url, String content){
        PostMethod method = null;
        try{
            method = new PostMethod(url);
            LOG.info("url :" +  url + "; method :post; req data : " + content);
            RequestEntity entity = new StringRequestEntity(content, "application/json", "UTF-8");
            method.setRequestEntity(entity);
            HTTP_CLIENT.executeMethod(method);
            String rspJson = new String(method.getResponseBody(), "UTF-8");
            LOG.info("rsp data : " + rspJson);
            return rspJson;
        }catch (IOException e){
            LOG.error("HttpPost失败:",e);
        }finally {
            if(method != null){
                method.releaseConnection();
            }
        }
        return null;
    }
    /**
     * 发送POST 请求
     * @param url 请求地址
     * @param charset 编码格式
     * @param params 请求参数
     * @return 响应
     * @throws IOException
     */
    public static String post(String url, String charset, Map params) {
        HttpURLConnection conn = null;
        OutputStreamWriter out = null;
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        StringBuffer result = new StringBuffer();
        try {
            conn = (HttpURLConnection)new URL(url).openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Accept-Charset", charset);
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            out = new OutputStreamWriter(conn.getOutputStream(), charset);
            out.write(buildQuery(params, charset));
            out.flush();
            inputStream = conn.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream);
            reader = new BufferedReader(inputStreamReader);
            String tempLine = null;
            while ((tempLine = reader.readLine()) != null) {
                result.append(tempLine);
            }

        } catch (IOException e) {
            LOG.error("Post失败:",e);
        } finally {
            try{
                if (out != null) {
                    out.close();
                }
                if (reader != null) {
                    reader.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            }catch (Exception e){
                LOG.error("请求关闭失败:",e);
            }

        }
        return result.toString();
    }

    /**
     * 将map转换为请求字符串
     * <p>data=xxx&msg_type=xxx</p>
     * @param params
     * @param charset
     * @return
     * @throws IOException
     */
    public static String buildQuery(Map<String, Object> params, String charset) throws IOException {
        if (params == null || params.isEmpty()) {
            return null;
        }

        StringBuffer data = new StringBuffer();
        boolean flag = false;

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            if (flag) {
                data.append("&");
            } else {
                flag = true;
            }
            data.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(), charset));
        }

        return data.toString();

    }

    public static void main(String[] args) throws Exception {

    }
}
